package org.alvin.i18n.ui;

import com.google.common.base.Strings;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

import java.io.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
/**
 * Pinyin4j 工具类
 *
 * @author: wangjing
 * @createTime: 2023-11-27 11:11
 * @version:
 * @Description:
 */
public class Pinyin4jUtil {
 
    private static Map<String, List<String>> pinyinMap = new HashMap<String, List<String>>();
    /**
     * 静态代码块 -->加载字典文件
     */
    static {
        try {
            // 这是自定义字典文件
            ClassLoader classLoader = Pinyin4jUtil.class.getClassLoader();
            initPinyin(classLoader.getResource("polyphonic_character_dict.txt").getFile());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
 
    /**
     * 初始化 所有的多音字词组
     *
     * @param filePath
     * @throws FileNotFoundException
     * @throws UnsupportedEncodingException
     */
    public static void initPinyin(String filePath) throws FileNotFoundException, UnsupportedEncodingException {
        // 读取多音字的全部拼音表;
        InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "utf-8");
        BufferedReader br = new BufferedReader(isr);
        String s = null;
        try {
            while ((s = br.readLine()) != null) {
                if (s != null) {
                    String[] arr = s.split("#");
                    String pinyin = arr[0];
                    String chinese = arr[1];
                    if (chinese != null) {
                        String[] strs = chinese.split(" ");
                        List<String> list = Arrays.asList(strs);
                        pinyinMap.put(pinyin, list);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
 
    /**
     * 汉字转汉语拼音
     *
     * @param text            汉语文本
     * @param pinyinCaseType  设置拼音大小写：UPPERCASE（大写）、LOWERCASE（小写）
     * @param pinyinToneType  设置拼音音调：WITHOUT_TONE（无音标）、WITH_TONE_MARK（拼音上面带音标）、WITH_TONE_NUMBER（用1-4表示音调）
     * @param pinyinVCharType 设置特殊音标ü：WITH_V（用 v 表示 ü）、WITH_U_AND_COLON（用 "u:" 表示 ü）、WITH_U_UNICODE（直接用 ü）
     *                        注意：toneType 为 WITH_TONE_MARK 时，charType 必须为 WITH_U_UNICODE，否则异常。
     * @return
     */
    public static String textToHanYuPinyin(String text, HanyuPinyinCaseType pinyinCaseType,
                                           HanyuPinyinToneType pinyinToneType, HanyuPinyinVCharType pinyinVCharType) {
        StringBuffer result = new StringBuffer();
        //将汉字参数去除空格后转化为数组
        char[] textChar = text.trim().toCharArray();
        // 拼音格式配置
        HanyuPinyinOutputFormat hanyuPinyinOutputFormat = new HanyuPinyinOutputFormat();
        hanyuPinyinOutputFormat.setCaseType(pinyinCaseType);
        hanyuPinyinOutputFormat.setToneType(pinyinToneType);
        // toneType 为 WITH_TONE_MARK 时，charType 必须为 WITH_U_UNICODE，否则异常。
        if (pinyinToneType.equals(HanyuPinyinToneType.WITH_TONE_MARK)) {
            pinyinVCharType = HanyuPinyinVCharType.WITH_U_UNICODE;
        }
        hanyuPinyinOutputFormat.setVCharType(pinyinVCharType);
        try {
            for (int i = 0; i < textChar.length; i++) {
                // 只为汉字进行拼音转换。
                char ch = textChar[i];
                if (Character.toString(ch).matches("[\\u4E00-\\u9FA5]+")) {
                    /**
                     * toHanyuPinyinStringArray
                     * 获取单个汉字的所有汉语拼音，即对于多音字，如"重"，则返回两个汉语拼音串：zhong、chong
                     * 这里暂时只取第一个，实际中这样是存在误差的，多音字很容易取错拼音.
                     */
                    String[] pinyinStringArray = PinyinHelper.toHanyuPinyinStringArray(ch,
                            hanyuPinyinOutputFormat);
 
                    String fullPinYin = pinyinStringArray[0];
 
                    // 多音字
                    if (pinyinStringArray.length != 1 && !pinyinStringArray[0].equals(pinyinStringArray[1])) {
                        String polyphonicCharacterHandleResult = polyphonicCharacterHandle(text, pinyinStringArray, i
                                , ch);
                        if (!Strings.isNullOrEmpty(polyphonicCharacterHandleResult)) {
                            fullPinYin = polyphonicCharacterHandleResult;
                        }
                    }
                    result.append(fullPinYin);
                } else {
                    result.append(ch);
                }
            }
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            e.printStackTrace();
        }
        return result.toString();
    }
 
    /**
     * 多音字处理
     *
     * @param text
     * @param pinyinStringArray
     * @param i
     * @return
     */
    public static String polyphonicCharacterHandle(String text, String[] pinyinStringArray, int i, char ch) {
        // 最终结果
        String result = "";
        // 多音字共有几个音
        int pinyinStringArrayLenth = pinyinStringArray.length;
        // 文本长度
        int textLength = text.length();
 
        String s = null;
 
        List<String> keyList = null;
        for (int x = 0; x < pinyinStringArrayLenth; x++) {
            String py = pinyinStringArray[x];
            // 过滤 u:
            if (py.contains("u:")) {
                py = py.replace("u:", "v");
            }
            keyList = pinyinMap.get(py);
 
            // 后向匹配2个汉字
            if (i + 3 <= textLength) {
                s = text.substring(i, i + 3);
                if (keyList != null && (keyList.contains(s))) {
                    result = py;
                    break;
                }
            }
 
            // 后向匹配 1个汉字
            if (i + 2 <= textLength) {
                s = text.substring(i, i + 2);
                if (keyList != null && (keyList.contains(s))) {
                    result = py;
                    break;
                }
            }
 
            // 前向匹配2个汉字
            if ((i - 2 >= 0) && (i + 1 <= textLength)) {
                s = text.substring(i - 2, i + 1);
                if (keyList != null && (keyList.contains(s))) {
                    result = py;
                    break;
                }
            }
 
            // 前向匹配1个汉字
            if ((i - 1 >= 0) && (i + 1 <= textLength)) {
                s = text.substring(i - 1, i + 1);
                if (keyList != null && (keyList.contains(s))) {
                    result = py;
                    break;
                }
            }
 
            // 前向1个，后向1个
            if ((i - 1 >= 0) && (i + 2 <= textLength)) {
                s = text.substring(i - 1, i + 2);
                if (keyList != null && (keyList.contains(s))) {
                    result = py;
                    break;
                }
            }
        }
        return result;
    }
 
 
    public static void main(String[] args) {
        String test = textToHanYuPinyin("我在重庆", HanyuPinyinCaseType.LOWERCASE, HanyuPinyinToneType.WITHOUT_TONE,
                HanyuPinyinVCharType.WITH_U_AND_COLON);
        System.out.println(test);
    }
 
 
}